/*
 * Copyright (C) 2014 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mylhyl.zxing.scanner.camera;


import com.mylhyl.zxing.scanner.CameraSurfaceView;
import ohos.agp.utils.Point;
import ohos.media.camera.device.CameraAbility;
import ohos.media.camera.device.FrameConfig;
import ohos.media.camera.params.Metadata;
import ohos.media.image.common.Size;

import java.util.Collection;
import java.util.Collections;
import java.util.List;


@SuppressWarnings("deprecation")
public final class CameraConfigurationUtils {

    private static final int MIN_PREVIEW_PIXELS = 480 * 320;
    private static final double MAX_ASPECT_DISTORTION = 0.15;

    private CameraConfigurationUtils() {
    }

    public static void setFocus(CameraAbility cameraAbility, FrameConfig.Builder builder, boolean autoFocus, boolean disableContinuous, boolean safeMode) {

        if (autoFocus) {
            //配置对焦模式
            builder.setAfMode(Metadata.AfMode.AF_MODE_CONTINUOUS, null);
        }
    }

    public static void setTorch(CameraAbility cameraAbility, FrameConfig.Builder builder, boolean on) {
        //当前相机支持的闪光灯取值范围
        int[] supportedFlashModes = cameraAbility.getSupportedFlashMode();
        String flashMode;
        if (on) {
            builder.setFlashMode(Metadata.FlashMode.FLASH_ALWAYS_OPEN);
        } else {
            builder.setFlashMode(Metadata.FlashMode.FLASH_CLOSE);
        }
    }

    public static Point findBestPreviewSizeValue(CameraAbility parameters, Point screenResolution) {

        //根据Class类型查询分辨率列表
        List<Size> rawSupportedSizes = parameters.getSupportedSizes(CameraSurfaceView.class);
        if (rawSupportedSizes == null) {
            return null;
        }

        StringBuilder previewSizesString = new StringBuilder();
        for (Size size : rawSupportedSizes) {
            previewSizesString.append(size.width).append('x').append(size.height).append(' ');
        }

        double screenAspectRatio = screenResolution.getPointX() / (double) screenResolution.getPointY();

        int maxResolution = 0;
        Size maxResPreviewSize = null;
        for (Size size : rawSupportedSizes) {
            int realWidth = size.width;
            int realHeight = size.height;
            int resolution = realWidth * realHeight;
            if (resolution < MIN_PREVIEW_PIXELS) {
                continue;
            }

            boolean isCandidatePortrait = realWidth < realHeight;
            int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
            int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;
            double aspectRatio = maybeFlippedWidth / (double) maybeFlippedHeight;
            double distortion = Math.abs(aspectRatio - screenAspectRatio);
            if (distortion > MAX_ASPECT_DISTORTION) {
                continue;
            }

            if (maybeFlippedWidth == screenResolution.getPointX() && maybeFlippedHeight == screenResolution.getPointY()) {
                Point exactPoint = new Point(realWidth, realHeight);
                return exactPoint;
            }

            if (resolution > maxResolution) {
                maxResolution = resolution;
                maxResPreviewSize = size;
            }
        }

        if (maxResPreviewSize != null) {
            Size closelySize = findCloselySize(maxResPreviewSize.width, maxResPreviewSize.height, rawSupportedSizes);
            Point largestSize = new Point(closelySize.width, closelySize.height);
            return largestSize;
        }
        return null;
    }

    private static int findSettableValue(String name,
                                         Collection<Integer> supportedValues,
                                         int... desiredValues) {
        if (supportedValues != null) {
            for (int desiredValue : desiredValues) {
                if (supportedValues.contains(desiredValue)) {
                    return desiredValue;
                }
            }
        }
        return 1;
    }

    /**
     * 通过对比得到与宽高比最接近的尺寸（如果有相同尺寸，优先选择）
     *
     * @param surfaceWidth  需要被进行对比的原宽
     * @param surfaceHeight 需要被进行对比的原高
     * @param preSizeList   需要对比的预览尺寸列表
     * @return 得到与原宽高比例最接近的尺寸
     */
    protected static Size findCloselySize(int surfaceWidth, int surfaceHeight, List<Size> preSizeList) {
        Collections.sort(preSizeList, new SizeComparator(surfaceWidth, surfaceHeight));
        return preSizeList.get(0);
    }
}
